package motiveai.tests;

import com.jme3.app.SimpleApplication;
import com.jme3.app.state.VideoRecorderAppState;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import java.util.ArrayList;
import motiveai.components.EntityAgent;
import motiveai.components.MotiveAI;
import motiveai.factors.Environment;
import motiveai.factors.EnvironmentDefinition;
import motiveai.factors.FactorBoolean;
import motiveai.learn.LearningType;

/**
 * test
 * @author oxplay
 */
public class Test3_BasicLearning extends SimpleApplication {

    private MotiveAI ai;
    private EnvironmentDefinition env;
    private Geometry box1;
    private Geometry box2;
    private Geometry box3;
    private Geometry box4;
    private Test3Agent agent;

    public static void main(String[] args) {
        Test3_BasicLearning app = new Test3_BasicLearning();
        app.start();
    }

    private Integer getCursorContactWithBox() {
        Vector3f origin = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.0f);
        Vector3f direction = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.3f);
        direction.subtractLocal(origin).normalizeLocal();
        Ray mouseRay = new Ray(origin, direction);
        CollisionResults results = new CollisionResults();
        box1.collideWith(mouseRay, results);
        if (results.size() > 0) {
            return 1;
        }
        box2.collideWith(mouseRay, results);
        if (results.size() > 0) {
            return 2;
        }
        box3.collideWith(mouseRay, results);
        if (results.size() > 0) {
            return 3;
        }
        box4.collideWith(mouseRay, results);
        if (results.size() > 0) {
            return 4;
        }
        return null;
    }
    private ActionListener actionListener = new ActionListener() {

        public void onAction(String name, boolean keyPressed, float tpf) {

            if (name.equals("Click") && keyPressed) {
                Integer boxSelected = getCursorContactWithBox();
                if (boxSelected != null) {
                    agent.pushedButton = boxSelected;
                    agent.boxes.get(boxSelected - 1).getControl(HighLightControl.class).highlight(0.5f, ColorRGBA.Red);
                }
            }
        }
    };

    private Geometry getBox(Vector3f vect) {
        Box boxx = new Box(0.5f, 0.5f, 0.5f);
        Geometry geom = new Geometry("Box" + vect, boxx);
        geom.setLocalTranslation(vect);
        Material mat1 = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        mat1.setColor("Diffuse", new ColorRGBA(0.3f, 0.3f, 0.3f, 1f));
        mat1.setColor("Ambient", new ColorRGBA(0.2f, 0.2f, 0.2f, 1f));
        mat1.setColor("Specular", new ColorRGBA(0.2f, 0.2f, 0.2f, 1f));
        mat1.setBoolean("UseMaterialColors", true);
        geom.setMaterial(mat1);
        HighLightControl highLightControl = new HighLightControl();
        geom.addControl(highLightControl);
        rootNode.attachChild(geom);
        return geom;
    }

    public void initKeys() {
        inputManager.addMapping("Click", new MouseButtonTrigger(mouseInput.BUTTON_LEFT));
        inputManager.addListener(actionListener, new String[]{"Click"});
    }

    @Override
    public void simpleInitApp() {
        setDisplayFps(false);       // to hide the FPS
        setDisplayStatView(false);  // to hide the statistics 
        //stateManager.attach(new VideoRecorderAppState(1f, 30)); //start recording
        AmbientLight al = new AmbientLight();
        rootNode.addLight(al);
        flyCam.setEnabled(false);
        ArrayList<Geometry> boxes = new ArrayList<Geometry>();
        box1 = getBox(new Vector3f(-3, 0, 0));
        box2 = getBox(new Vector3f(-1, 0, 0));
        box3 = getBox(new Vector3f(1, 0, 0));
        box4 = getBox(new Vector3f(3, 0, 0));
        boxes.add(box1);
        boxes.add(box2);
        boxes.add(box3);
        boxes.add(box4);
        env = new EnvironmentDefinition();
        env.setFactorDefinition("noPush", new FactorBoolean(true, true, 1));
        env.setFactorDefinition("pushed1", new FactorBoolean(false, false, 1));
        env.setFactorDefinition("pushed2", new FactorBoolean(false, false, 1));
        env.setFactorDefinition("pushed3", new FactorBoolean(false, false, 1));
        env.setFactorDefinition("pushed4", new FactorBoolean(false, false, 1));
        ai = new MotiveAI<EntityAgent>(env, LearningType.LOW_PRECISE, 100);
        ai.registerBehaviour(Test3Idle.class);
        ai.registerBehaviour(Test3Push1.class);
        ai.registerBehaviour(Test3Push2.class);
        ai.registerBehaviour(Test3Push3.class);
        ai.registerBehaviour(Test3Push4.class);
        agent = new Test3Agent();
        agent.boxes = boxes;
        ai.addAgent(agent);
        ai.addSensor(new Test3Sensor());
        ai.setUpdateRate(0);
        initKeys();
        stateManager.attach(ai);
    }

    @Override
    public void simpleUpdate(float tpf) {
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
}
